package com.easy.activiti.mapper;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;

import static java.lang.Class.forName;

public class ProxyFactory<T> {

    private Class<T> daoClazz;
    private JdbcTemplate jdbcTemplate;
    public ProxyFactory(Class<T> daoClass,JdbcTemplate jdbcTemplate){
        this.daoClazz = daoClass;
//        Type[] interTypes = daoClazz.getGenericInterfaces();
//        ParameterizedType pType=(ParameterizedType) interTypes[0];
//        Type[] types = pType.getActualTypeArguments();
//        this.entityClass=(Class) types[0];
        this.jdbcTemplate = jdbcTemplate;
    }

    public  T getProxyInstance() {
        return (T) Proxy.newProxyInstance(
                daoClazz.getClassLoader(),
                new Class[]{daoClazz},
                (Object proxy, Method method, Object[] args)->{
                    Annotation[] annotations =   method.getAnnotations();
                    if(annotations.length>0){
                        String sql = null;
                        if(annotations[0] instanceof Insert) {
                            Insert annotation = (Insert) annotations[0];
                            sql = annotation.value()[0];
                        }else if(annotations[0] instanceof Select) {
                            Select annotation = (Select) annotations[0];
                            sql = annotation.value()[0];
                        }else if(annotations[0] instanceof Delete) {
                            Delete annotation = (Delete) annotations[0];
                            sql = annotation.value()[0];
                        }else{
                            new IllegalArgumentException("未支持的方法");
                        }
                        Parameter[] parameters = method.getParameters();
                        // 遍历每个参数，获取注解
                        for (int i = 0; i < parameters.length; i++) {
                            Parameter parameter = parameters[i];
                            String name = parameter.getName();
                            // 检查是否有 Param 注解
                            if (parameter.isAnnotationPresent(Param.class)) {
                                // 获取注解
                                Param annotation = parameter.getAnnotation(Param.class);
                                name = annotation.value();
                            }

                            //如果是insert 可能会是对象或者是list
                            if(annotations[0] instanceof Insert) {
                                String columns = sql.substring(sql.indexOf("(")+1, sql.indexOf(")"));
                                List<String> values = new ArrayList<>();
                                if( args[i] instanceof List){
                                    for (Object o : (List) args[i]) {
                                        List<String> value = new ArrayList<>();
                                        for (String column : columns.split(",")) {
                                            Field field = o.getClass().getDeclaredField(column.trim());
                                            field.setAccessible(true);
                                            value.add(Optional.ofNullable( field.get(o)).orElse("").toString());
                                        }
                                        values.add("('"+value.stream().collect(Collectors.joining("','"))+"')");
                                    }
                                    sql += " values "+values.stream().collect(Collectors.joining(","));
                                }
                            }
                            if (sql.contains(String.format("#{%s}", name))) {
                                sql = sql.replace(String.format("#{%s}",  name), "'"+args[i].toString()+"'");
                            } else if (sql.contains(String.format("${%s}", name))) {
                                sql = sql.replace(String.format("${%s}", name), args[i].toString());
                            }
                        }
                        System.out.println(sql);
                        if(annotations[0] instanceof Insert) {
                            jdbcTemplate.execute(sql);
                            return 1;
                        }else if(annotations[0] instanceof Select) {
                            Type returnType = method.getGenericReturnType();
                            if (returnType instanceof ParameterizedType) {
                                ParameterizedType parameterizedType = (ParameterizedType) returnType ;
                                // 获取泛型类型
                                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                                //如果还是一个泛型
                                if(actualTypeArguments[0].getClass().isAssignableFrom(ParameterizedTypeImpl.class)){
                                    if(Map.class.isAssignableFrom(((ParameterizedTypeImpl) actualTypeArguments[0]).getRawType())){
                                        List<Map<String,Object>> linkCaseInsensitiveMapList = jdbcTemplate.queryForList(sql);
                                        List<HashMap<String, Object>> hashMapList = linkCaseInsensitiveMapList.stream()
                                                .map(linkCaseInsensitiveMap -> {
                                                    HashMap<String, Object> hashMap = new HashMap<>(linkCaseInsensitiveMap);
                                                    return hashMap;
                                                })
                                                .collect(Collectors.toList());
                                        return hashMapList;
                                    }
                                }else{
                                    if( Map.class.isAssignableFrom(actualTypeArguments[0].getClass() )){
                                        List<Map<String,Object >> list = jdbcTemplate.queryForList(sql);
                                        return list;
                                    }else{
                                        Class type =  (Class) actualTypeArguments[0];
                                        RowMapper rowMapper = (RowMapper) Class.forName(type.getName()+"RowMapper").newInstance();
                                        return jdbcTemplate.query(sql, rowMapper);
                                    }
                                }
                            }
                        }else if(annotations[0] instanceof Delete) {
                            jdbcTemplate.execute(sql);
                            return 1;
                        }
                    }else{
                        new IllegalArgumentException("不是sql注解");
                    }
                    return null;
                }
        );
    }
}
